//
//  HSHttpTool.m
//  AFNetworking
//
//  Created by huang on 2018/8/6.
//

#import "HSHttpTool.h"
#import "AFNetworking.h"
#import "HSCustomURLProtocol.h"
#import "HSHttpConfig.h"

@implementation HSHttpTool

//防止内存泄露
+ (AFHTTPSessionManager *)sharedHttpSession
{
    static AFHTTPSessionManager *manager;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //1.防止dns挟持
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSArray *protocolArray = @[[HSCustomURLProtocol class]];
        configuration.protocolClasses = protocolArray;
        
        manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configuration];
        manager.requestSerializer.timeoutInterval = 10;
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html",@"text/json", @"text/javascript",@"text/plain", nil];
        
        //2.导入证书
        if ([HSHttpConfig sharedConfig].cerPath.length > 0) {
            [HSHttpTool addHttpsCerWithSessionManager:manager];
        }
    });
    return manager;
}

#pragma mark 取消所有请求
+ (void)cancelAllRequest
{
    AFHTTPSessionManager *manager = [HSHttpTool sharedHttpSession];
    [manager.operationQueue cancelAllOperations];
}

#pragma mark 发起请求
+ (void)requestWithMethod:(HSRequestMethod)method path:(NSString *)path params:(NSDictionary *)params success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    AFHTTPSessionManager *manager = [HSHttpTool sharedHttpSession];
    NSString *urlStr = [HSHttpTool correctPath:path];
    switch (method) {
        case HSRequestMethodGET: {
            [manager GET:urlStr parameters:params progress:nil success:success failure:failure];
        }
            break;
        case HSRequestMethodPOST: {
            [manager POST:urlStr parameters:params progress:nil success:success failure:failure];
        }
            break;
        case HSRequestMethodPUT: {
            [manager PUT:urlStr parameters:params success:success failure:failure];
        }
            break;
        case HSRequestMethodPATCH: {
            [manager PATCH:urlStr parameters:params success:success failure:failure];
        }
            break;
        case HSRequestMethodDELETE: {
            [manager DELETE:urlStr parameters:params success:success failure:failure];
        }
            break;
            
        default:
            break;
    }
}

#pragma mark 获取正确路径
+ (NSString *)correctPath:(NSString *)path
{
    if ([path hasPrefix:@"http"]) {
        path = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        return path;
    }
    
    if ([HSHttpConfig sharedConfig].baseUrl.length > 0) {
        NSString *baseURLString = [NSString stringWithFormat:@"%@%@",[HSHttpConfig sharedConfig].baseUrl,path];
        baseURLString = [baseURLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        return baseURLString;
    }
    
    return path;
}

#pragma mark 添加证书
+ (void)addHttpsCerWithSessionManager:(AFHTTPSessionManager *)manager
{
    __weak typeof(manager)wManager = manager;
    //导入证书
    [manager setSessionDidReceiveAuthenticationChallengeBlock:^NSURLSessionAuthChallengeDisposition(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential *__autoreleasing *_credential) {
        
        SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
        
        //导入多张CA证书
        NSString *cerPath = [[NSBundle mainBundle] pathForResource:[HSHttpConfig sharedConfig].cerPath ofType:@"cer"];//自签名证书
        NSData* caCert = [NSData dataWithContentsOfFile:cerPath];
        NSArray *cerArray = @[caCert];
        wManager.securityPolicy.pinnedCertificates = [NSSet setWithArray:cerArray];
        
        SecCertificateRef caRef = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)caCert);
        NSCAssert(caRef != nil, @"caRef is nil");
        
        NSArray *caArray = @[(__bridge id)(caRef)];
        NSCAssert(caArray != nil, @"caArray is nil");
        
        OSStatus status = SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)caArray);
        SecTrustSetAnchorCertificatesOnly(serverTrust,NO);
        NSCAssert(errSecSuccess == status, @"SecTrustSetAnchorCertificates failed");
        
        NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        __autoreleasing NSURLCredential *credential = nil;
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            if ([wManager.securityPolicy evaluateServerTrust:challenge.protectionSpace.serverTrust forDomain:challenge.protectionSpace.host]) {
                credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
                if (credential) {
                    disposition = NSURLSessionAuthChallengeUseCredential;
                } else {
                    disposition = NSURLSessionAuthChallengePerformDefaultHandling;
                }
            } else {
                disposition = NSURLSessionAuthChallengeCancelAuthenticationChallenge;
            }
        } else {
            disposition = NSURLSessionAuthChallengePerformDefaultHandling;
        }
        CFRelease(caRef);
        return disposition;
    }];
}

@end
